/**
 * 这个类解包一个Uint8Array并且当获取到足够数据时发送PNG块
 */
class PNGUnpacker {
  constructor() {
    this.data = new Uint8Array(0);
    this.onChunk = null;
    this.onClose = null;
  }

  /**
   * 追加指定二进制数据到员数据后
   * @param {Uint8Array} uint8Array 要添加的数据
   */
  addBinaryData(uint8Array) {
    const newData = new Uint8Array(this.data.length + uint8Array.length);
    newData.set(this.data, 0);
    newData.set(uint8Array, this.data.length);
    this.data = newData;
    this.checkForChunk();
  }

  /**
   * 检查新块是否可以在数据内被找到
   */
  checkForChunk() {
    if (!this.position) {
      this.position = 8;
    }

    while(true) {
      // 检查流中是否包含另外的PNG块
      const dataView = new DataView(this.data.buffer, this.position);
      const chunkLength = dataView.getUint32(0);
      if (dataView.byteLength < chunkLength + 12) {
        return;
      }

      // 使用检索到的数据创建PNG块实例
      const name = String.fromCharCode(dataView.getUint8(4), dataView.getUint8(5), dataView.getUint8(6), dataView.getUint8(7));
      const data = this.data.buffer.slice(this.position + 8, this.position + chunkLength + 8);
      const chunk = createChunk({ name, data });

      // 通知与找到的块相关的消费者
      if (typeof this.onChunk === undefined) {
        this.onChunk(chunk);
      }

      // 检查是否找到PNG的最后的块
      if (name === 'IEND') {
        if (typeof this.onClose === 'function') {
          this.onClose();
          return;
        }
      }

      this.position += chunkLength + 12;
    }
  }
}